/**
 * 工具类
 */
var Util = {
	/**
	 * 空（包括0）
	 * @param v
	 */
	nvl: function(v) {		
		if ('' == v || null == v || 'null' == v|| 0 == v) {
			return true;
		}
		return false;
	},
	
	/**
	 * 空（不包括0）
	 * @param v
	 */
	nvlExc: function(v) {		
		if (('' == v || null == v || 'null' == v) && 0 != v) {
			return true;
		}
		return false;
	},
	
	/**
	 * 空（包括0）
	 * @param v
	 */
	nvlZero: function(v) {		
		if ('' == v || null == v || 'null' == v || v.toString() == '0') {
			return true;
		}
		return false;
	},
	/**
	 * 未定义
	 * @param v
	 */
	undfd: function(v) {
		if (typeof (v) == 'undefined') {
			return true;
		}
		return false;
	},
	isUndefined : function(v){
		if (typeof(v) == "undefined") { 
			return true;
		}  
		return false;
	},
	/**
	 * 根据id获取对象引用
	 * @param x
	 */
	id: function(x) {
		if (typeof (x) == 'string') {
			return document.getElementById(x);
		}
		return x;
	},
	/**
	 * 信息
	 */
	msg: {
		isMask:true,
		/**
		 * 提示框
		 * @param msg 提示信息
		 * @param title
		 * @param type 'info','error','warning'
		 */
		alert: function(msg, title, type) {
			if (Util.undfd(msg) || Util.nvl(msg)) {
				return false;
			}
			title = (Util.undfd(title) || Util.nvl(title)) ? '提示' : title;
			type = (Util.undfd(type) || Util.nvl(type)) ? 'info' : type;
			if (!Util.undfd($.messager) && !Util.nvl($.messager)) {
				$.messager.alert(title, msg, type);
			} else {
				alert(msg);
			}
		},
		/**
		 * 等待遮罩层
		 */
		waiting: function() {
			var defMsg = '正在处理，请稍待。。。';  
			if(!$("#mask")[0])
		        $("<div id='mask' class=\"datagrid-mask\" style='z-index:1000'></div>").appendTo("body"); 
		    if(!$("#maskMsg")[0]) 
		        $("<div id='maskMsg' class=\"datagrid-mask-msg\" style='z-index:1001;left:50%;margin-left:-75px;'>"+defMsg+"</div>").appendTo("body");  
		        
			$("#mask,#maskMsg").show();
		},
		/**
		 * 等待遮罩层移除
		 */
		waitOver: function() {
			$("#mask,#maskMsg").hide();
		}
	},
	date : {
		/**
    	 * 将Date转化为指定格式的String，月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 
    	 * 可以用 1-2 个占位符，年(y)可以用1-4个占位符，毫秒(S)只能用1个占位符(是1-3位的数字)   
    	 * @param d 日期对象
    	 * @param fmt 格式串
    	 * @return 指定格式后的日期字符串
    	 * 例子：  
    	 * (format(d,'yyyy-MM-dd hh:mm:ss.S') ==> 2006-07-02 08:09:04.423 
    	 * (format(d,'yyyy-M-d h:m:s.S')      ==> 2006-7-2 8:9:4.18 
    	 */
		format : function(d, fmt) {
			var o = {
				'M+': d.getMonth() + 1,// 月份
				'd+': d.getDate(),// 日
				'h+': d.getHours(),// 小时
				'm+': d.getMinutes(),// 分
				's+': d.getSeconds(),// 秒
				'q+': Math.floor((d.getMonth() + 3) / 3),// 季度
				'S': d.getMilliseconds()// 毫秒
			};
			if (/(y+)/.test(fmt)) {
				fmt = fmt.replace(RegExp.$1, (d.getFullYear() +'')
						.substr(4 - RegExp.$1.length));
			}
			for (var k in o) {
				if (new RegExp('('+ k +')').test(fmt)) {
					fmt = fmt.replace(RegExp.$1,
							(RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k])
									.substr(('' + o[k]).length)));
				}
			}
			return fmt;
		},
		/**
		 * 创建基于easyui databox的月视图组件
		 * @param {} dateboxId
		 */
		monthViewDateBox: function(dateboxId,onSelect) {
			$(dateboxId).datebox({
	            onShowPanel: function () {//显示日趋选择对象后再触发弹出月份层的事件，初始化时没有生成月份层
	                span.trigger('click'); //触发click事件弹出月份层
	                if (!tds) setTimeout(function () {//延时触发获取月份对象，因为上面的事件触发和对象生成有时间间隔
	                    tds = p.find('div.calendar-menu-month-inner td');
	                    tds.click(function (e) {
	                        e.stopPropagation(); //禁止冒泡执行easyui给月份绑定的事件
	                        var year = /\d{4}/.exec(span.html())[0];//得到年份
	                        var month = parseInt($(this).attr('abbr'), 10); //月份
	                        $(dateboxId).datebox('hidePanel');//隐藏日期对象
	                        
	                        $(dateboxId).datebox('setValue', year + '-' + month); //设置日期的值
	                        
	                        if(onSelect)onSelect(year + '-' +month);
	                    });
	                }, 0)
	            },
	            parser: function (s) {//配置parser，返回选择的日期
	                if (!s) return new Date();
	                var arr = s.split('-');
	                return new Date(parseInt(arr[0], 10), parseInt(arr[1], 10) - 1, 1);
	            },
	            formatter: function (d) {
	            	return Util.date.format(d,'yyyy-MM');
	            }//配置formatter，只返回年月
	        });
	        var p = $(dateboxId).datebox('panel'), //日期选择对象
	            tds = false, //日期选择对象中月份
	            span = p.find('span.calendar-text'); //显示月份层的触发控件
	    
		},
		/**
		 * 获得指定年月前推n年的时间
		 * now 起始时间(时间格式或yyyy/MM/dd等有正常的分隔符数据格式,建议'yyyy/MM/dd')
		 * num 前推间隔时间
		 * fmt 格式化时间输出格式
		 */
		getIntervalYear: function(now, num, fmt){
			if (!now) {
				return null;
			}
			if(!now instanceof Date){
				now = new Date(now);
				if (!now) {
					return null;
				}
			}
			now.setDate(1);// 设置为月初1号
			var years = [];
			for (var i = 0; i < num; i++) {
				years[i] = Util.date.format(now, fmt ? fmt : 'yyyy');
				now.setFullYear(now.getFullYear() - 1);
			}
			return years;
		},
		/**
		 * 获得指定年月前推n月的时间
		 * now 起始时间(时间格式或yyyy/MM/dd等有正常的分隔符数据格式,建议'yyyy/MM/dd')
		 * num 前推间隔时间
		 * fmt 格式化时间输出格式
		 */
		getIntervalMonth: function(now, num, fmt){
			if (!now) {
				return null;
			}
			if(!now instanceof Date){
				now = new Date(now);
				if (!now) {
					return null;
				}
			}
			now.setDate(1);// 设置为月初1号
			var months = [];
			for (var i = 0; i < num; i++) {
				months[i] = Util.date.format(now, fmt ? fmt : 'yyyyMM');
				now.setMonth(now.getMonth() - 1);
			}
			return months;
		},
		/**
		 * 获得指定年周前推n周的时间
		 * now 起始时间(时间格式或yyyy/WW等有正常的分隔符数据格式,建议'yyyy/WW')
		 * num 前推间隔时间
		 * format 格式化时间输出格式
		 */
		getIntervalWeek: function(now, num){
			if ('' == now || null == now) {
				return now;
			}
			var Y = parseInt(now.substring(0, 4));
			var W = parseInt(now.substring(4, 6), 10);
			if (W > num) {
				var cw = W - num + 1;
				return Y.toString() + (cw < 10 ? ('0'+ cw) : (''+ cw));
			} else {
				var cw = 53 - num - W + 1;
				return (Y - 1).toString() + (cw < 10 ? ('0'+ cw) : (''+ cw));
			}
		},
		/**
		 * 只接受yyyy#MM#格式的数据请求
		 */
		dateStrToDate : function(dateStr){
			return new Date(dateStr.substring(0,4)+"/"+dateStr.substring(5,7)	+"/01 00:00:00");
		},
		/**
		 * 字符串转化为日期
		 * @param str
		 */
		strToDate: function(str) {
			if (!str) {
				return null;
			}
			var d = null;
			if (str.indexOf('-') > 0 || str.indexOf('/') > 0) {
				d = new Date(str);
			} else if (str.length == 6) {
				d = new Date();
				d.setFullYear(str.substr(0, 4));
				d.setMonth(parseInt(str.substr(4, 2)) - 1);
			} else if (str.length == 10) {
				d = new Date();
				d.setFullYear(str.substr(0, 4));
				d.setMonth(parseInt(str.substr(4, 2)) - 1);
				d.setDate(str.substr(6, 2));
			}
			return d;
		},
		/**
		 * 两个日期相差天数
		 */
		dateDifferDays: function(sd, ed) {
			if (!sd && !sd) {
				return null;
			}
			// 相差秒数
			var ss = (ed.getTime() - sd.getTime()) / 1000;
			return ss / (24 * 60 * 60);
		}
	},
	/**
	 * 服务器返回错误统一处理
	 * {stateCode: int,stateMsg: string,...}
	 * @param data
	 * @param errMsg
	 */
	error: function(data, errMsg) {
		if (!Util.undfd(data.stateCode) && !Util.nvl(data.stateCode)
				&& data.stateCode == 400) {
			var msg = errMsg ? errMsg : data.stateMsg;
			if (!Util.undfd($.messager) && !Util.nvl($.messager)) {
				$.messager.alert('错误信息', msg, 'error');
			} else {
				alert(data.stateMsg);
			}
			return true;// 有错误
		}
		return false;// 无错误
	},
	doPostCount: 0,
	/**
	 * ajax post请求
	 * @param url
	 * @param param
	 * @param succ 执行成功回调函数
	 * @param succMsg 执行成功提示信息
	 * @param err 执行失败回调函数
	 * @param errMsg 执行失败提示信息
	 */
	doPost: function(url, param, succ, succMsg, err, errMsg) {			
		// ajax请求
		$.ajax({
			url: CONTEXT_PATH + url,
			data: param,
			type: 'POST',
			dataType: 'json',
			cache: false,
			beforeSend: function() {
				Util.doPostCount++;
				// 等待
				if(Util.msg.isMask){
					Util.msg.waiting();
				}
				Util.msg.isMask=true;
			},
			success: function(json) {
				if (Util.doPostCount > 0) {
					Util.doPostCount--;
				}
				if (Util.doPostCount == 0) {
					// 等待结束
					Util.msg.waitOver();
				}
				if (!Util.error(json, errMsg)) {// 无错误
					if (typeof (succ) === 'function') {
						succ(json);
					}
				} else {// 有错误
					if (typeof (err) === 'function') {
						err(json);
					}
				}
			},
			/*complete: function() {
				if (Util.doPostCount > 0) {
					Util.doPostCount--;
				}
				if (Util.doPostCount == 0) {
					// 等待结束
					Util.msg.waitOver();
				}
			},*/
			error: function(jqXHR, textStatus, errorThrown) {
				if (Util.doPostCount > 0) {
					Util.doPostCount--;
				}
				if (Util.doPostCount == 0) {
					// 等待结束
					Util.msg.waitOver();
				}
				if (typeof (err) === 'function') {
					err(jqXHR, textStatus, errorThrown, errMsg);
					if (!Util.undfd(errMsg) && !Util.nvl(errMsg)) {
						Util.msg.alert(errMsg, '提示', 'error');
					}
				} else {
					if (!Util.undfd(errMsg) && !Util.nvl(errMsg)) {
						Util.msg.alert(errMsg, '提示', 'error');
					} else {
						//Util.msg.alert(jqXHR.status + ':' + jqXHR.statusText + ',' + textStatus, '提示', 'error');
					}
				}
			}
		});
	},
	/**
	 * ajax get请求
	 * @param url
	 * @param param
	 * @param succ 执行成功回调函数
	 * @param succMsg 执行成功提示信息
	 * @param err 执行失败回调函数
	 * @param errMsg 执行失败提示信息
	 */
	doGet: function(url, param, succ, succMsg, err, errMsg) {
		// ajax请求
		$.ajax({
			url: CONTEXT_PATH + url,
			data: param,
			type: 'GET',
			dataType: 'json',
			cache: false,
			beforeSend: function() {
				// 等待
				Util.msg.waiting();
			},
			success: function(json) {
				// 等待结束
				Util.msg.waitOver();
				if (!Util.error(json, errMsg)) {// 无错误
					if (typeof (succ) === 'function') {
						succ(json);
					}
				} else {// 有错误
					if (typeof (err) === 'function') {
						err(json);
					}
				}
			},
			complete: function() {
				// 等待结束
				Util.msg.waitOver();
			},
			error: function(jqXHR, textStatus, errorThrown) {
				// 等待结束
				Util.msg.waitOver();
				if (typeof (err) === 'function') {
					err(jqXHR, textStatus, errorThrown, errMsg);
					if (!Util.undfd(errMsg) && !Util.nvl(errMsg)) {
						Util.msg.alert(errMsg, '提示', 'error');
					}
				} else {
					if (!Util.undfd(errMsg) && !Util.nvl(errMsg)) {
						Util.msg.alert(errMsg, '提示', 'error');
					} else {
						//Util.msg.alert(jqXHR.status +':'+ jqXHR.statusText +','+ textStatus, '提示', 'error');
					}
				}
			}
		});
	},
	/**
	 * 简单的ajax post请求
	 * @param url
	 * @param param
	 * @param fn
	 * @param type
	 */
	post: function(url, param, fn, type) {			
		$.post(CONTEXT_PATH + url, param, fn, type);
	},
	/**
	 * 简单的ajax get请求
	 * @param url
	 * @param param
	 * @param fn
	 */
	get: function(url, param, fn) {
		$.get(CONTEXT_PATH + url, param, fn);
	},
	/**
	 * 设置标签html内容
	 * @param id 控件id
	 * @param html 内容
	 */
	setHtml: function(id, html) {
		if (!Util.undfd(id) && !Util.nvl(id)) {
			$('#'+ id).html(Util.defVal(html));
		}
	},
	/**
	 * 设置attr值
	 * @param id
	 * @param attr
	 * @param val
	 */
	setAttr: function(id, attr, val) {
		if (!Util.undfd(id) && !Util.nvl(id)
				&& !Util.undfd(attr) && !Util.nvl(attr)
				&& !Util.undfd(val) && !Util.nvl(val)) {
			$('#'+ id).attr(attr, val);
		}
	},
	/**
	 * 移除class
	 * @param id 控件id
	 * @param className
	 */
	removeClass: function(id, className) {
		if ($('#'+ id).hasClass(className)) {
			$('#'+ id).removeClass(className);
		}
	},
	/**
	 * 添加class
	 * @param id 控件id
	 * @param className
	 */
	addClass: function(id, className) {
		if (!$('#'+ id).hasClass(className)) {
			$('#'+ id).addClass(className);
		}
	},
	/**
	 * 默认值
	 * @param v
	 * @param def
	 */
	defVal: function(v, def) {
		if (Util.nvlExc(v) || Util.undfd(v)) {
			return def ? def : '-';
		} else {
			return v;
		}
	},
	/*表头列排序
	 * @param id 表头id
	 * @param ds 数据
	 * @param def 默认排序列
	 * @param cols 表头列字段 
	 * @param fn 加载数据函数
	 */
	sort: function(id,ds,def,cols,fn){
		var clicks=[];					
		$("#"+id).children().each(function(idx){	
			clicks.push(false);	
			$(this).unbind("click");
			$(this).bind("click",function(obj){				
				if(!ds[0]||!/-?\d+/ig.test(ds[0][cols[idx]])) return;				
				$("#"+id).children().removeClass("asc").removeClass("desc");
				if(clicks[idx]){					
					$(this).addClass("asc");	
					ds.sort(function(a,b){
						return a[cols[idx]]-b[cols[idx]]								
					})
				}
				else{
					$(this).addClass("desc");						
					ds.sort(function(a,b){
						return b[cols[idx]]-a[cols[idx]]						
					})
				}									
				if(fn)fn(ds)
				clicks[idx]=!clicks[idx];						
			})
		})
		if(typeof(def)=="object"){
			clicks[def.idx]=def.sort=="asc"?true:false;
			$("#"+id).children().eq(def.idx).click();
		}
		else
			$("#"+id).children().eq(def).click();
	},
	
	/**
	 * 将值输出到页面指定的标签中
	 * @author 施建峰
	 */
	setValToHtml:function(id,val){
		$("#"+id).html(val);
	},
	
	/**
	 * 默认值
	 * @param v
	 * @param def
	 */
	valFormat: function(v, def) {
		if (Util.nvl(v) || Util.undfd(v)) {
			return def ? def : '';
		} else {
			return parseFloat(v).toFixed(2);
		}
	},
	
	/**
	 * 获取url参数
	 * @param name
	 */
	getURLParameter: function(name) {
		var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
		var r = window.location.search.substr(1).match(reg);
		if (r != null) return r[2]; return null;
	},
	/**
	 * EasyUI combox
	 */
	combox: {
		loader: function(param, success, error) {
			var opts = $(this).combobox('options');
			if (!opts.url) {
				return false;
			}
			$.ajax({
				type: opts.method,
				url: opts.url,
				data: param,
				dataType: 'json',
				success: function(data) {
					success(data);
				},
				error: function() {
					error.apply(this, arguments);
				}
			});
		}
	},
	/**
	 * EasyUI DataGrid根据字段动态合并单元格
	 * @param id 要合并table的id
	 * @param fldStr 要合并的列,用逗号分隔(例如：'name,department,office');
	 */
	dgMergeCells: function(id, fldStr){
		if (Util.undfd(id) || Util.nvl(id) || Util.undfd(fldStr) || Util.nvl(fldStr)) {
			return;
		}
	    var dg = $('#'+ id);
		if (dg[0]) {// 表格对象存在
		    var ds = dg.datagrid('getRows');
		    if(!Util.undfd(ds) && !Util.nvl(ds) && ds instanceof Array && ds.length > 0) {
			    var flds = fldStr.split(',');
			    var fld,pVal,lpVal,cVal,lcVal,span;
			    for (var i = (flds.length - 1); i >= 0; i--) {
			        fld = flds[i];
			        cVal = '';
			        pVal = '';
			        lcVal = '';
			        lpVal = '';
			        span = 1;
			        for (var row = 0; row <= ds.length; row++) {
			            if (row == ds.length) {
			                cVal = '';
			            } else {
			                cVal = ds[row][fld];
			                if (i == 0) {
			                	lcVal = '';
			                } else {
			                	lcVal = ds[row][flds[i - 1]];
			                }
			            }
			            if (pVal == cVal && lpVal == lcVal) {
			            	span += 1;
			            } else {
			                var idx = row - span;
			                dg.datagrid('mergeCells', {
			                    index: idx,
			                    field: fld,
			                    rowspan: span,
			                    colspan: null
			                });
			                span = 1;
			                pVal = cVal;
			                lpVal = lcVal;
			            }
			        }
			    }
		    }
		}
	},
	/**
	 *  EasyUI DataGrid根据字段动态合并footer部分行单元格
	 *  @param id
	 *  @param field 开始合并的列
	 *  @param colspan 合并的行数
	 */
	dgMergeFooterCells: function(id, field, colspan) {
		if (id && field && colspan) {
			$('#'+ id).datagrid('mergeCells',{
				index: 0,
                field: field,
                rowspan: null,
                colspan: Number(colspan),
                type: 'footer'
			});
		}
	},
	/**
	 * EasyUI DataGrid提示框format
	 */
	dgTooltipFormat: function(value, row, index) {
		var rs = '';
		if (!Util.undfd(value) && !Util.nvl(value)) {
			rs = '<div class="easyui-tooltip" title="'+ value +'">'+ value +'</div>';
		}
		return rs;
	},
	/**
	 * EasyUI DataGrid秒转化为天单元格格式化
	 */
	dgSecondToDayFormat: function(value, row, index) {
		var rs = '';
		if (!Util.undfd(value) && !Util.nvlExc(value) && value != '-') {
			rs = Util.secondToDays(value);
		}
		return rs;
	},
	/**
	 * 解析阀值状态灯（预警区间闭包）
	 * @param val 值
	 * @param thrshds 阀值数组
	 */
	parseThrshdSttLamp: function(val, thrshds) {
		var rs = '';
		if (!Util.nvlExc(val) && !Util.undfd(val)
				&& !Util.nvl(thrshds) && !Util.undfd(thrshds) && thrshds.length > 0) {
			val = parseFloat(val);
			var stts = '1';
			$.each(thrshds, function(index, item, ds) {
				if (item.THRSHD_STTS == '1' && val < parseFloat(item.MAX_THRSHD)) {
					stts = '1';
					return false;
				}
				if (item.THRSHD_STTS == '3' && val > parseFloat(item.MIN_THRSHD)) {
					stts = '3';
					return false;
				}
    			if (item.THRSHD_STTS == '2' && val >= parseFloat(item.MIN_THRSHD) && val <= parseFloat(item.MAX_THRSHD)) {
					stts = '2';
					return false;
				}
			});
			rs = '<div class="cntt-box stt-lamp-'+ stts +'">&nbsp;</div>';
		}
		return rs;
	},
	/**
	 * 默认值
	 * @param v
	 * @param def
	 */
	valFormat: function(v, def) {
		if (Util.nvl(v) || Util.undfd(v)) {
			return def ? def : '';
		} else {
			return parseFloat(v).toFixed(2);
		}
	},
	/**
	 * 设置标签html内容
	 * @param id 控件id
	 * @param html 内容
	 */
	setHtml: function(id, html) {
		if (!Util.undfd(id) && !Util.nvl(id)) {
			$('#'+ id).html(Util.defVal(html));
		}
	},
	/**
	 * 移除class
	 * @param id 控件id
	 * @param className
	 */
	removeClass: function(id, className){
		if($('#'+ id).hasClass(className)){
			$('#'+ id).removeClass(className);
		}
	},
	/**
	 * 添加class
	 * @param id 控件id
	 * @param className
	 */
	addClass: function(id, className) {
		if (!$('#'+ id).hasClass(className)) {
			$('#'+ id).addClass(className);
		}
	},
	/**
	 * 构建增幅/率（带红/绿三角）
	 * @param id
	 * @param v
	 * @param sfx 值后缀：‘%’
	 * @param ud 逆向指标
	 */
	buildDR: function(id, v, sfx, ud) {
		if (id && v) {
			// >=0 上绿
			var cn = 'val-col-icon-g-u';
			// < 0 下红
			var ocn = 'val-col-icon-r-d color-red';
			if (ud) {// 逆向指标
				// >= 0 上红
				cn = 'val-col-icon-r-u color-red';
				// < 0 下绿
				ocn = 'val-col-icon-g-d';
			}
			if (v < 0) {
				cn = ocn;
			}
			Util.setHtml(id, "  " + Math.abs(v) + (sfx ? sfx : ''));
			$('#'+ id).removeClass();
			Util.addClass(id, cn);
		}
	},
	/**
	 * EasyUI DataGrid字体颜色format
	 */
	dgToolFontColorFormat: function(value, row, index) {
		var names= ['优秀','正常','蓝色预警','红色预警','良好'];
		var colors=['#008000','#800080','#0000FF','#FF0000','#333333'];
		var rs = '';
		if (!Util.undfd(value) && !Util.nvl(value)) {
			for(var i=0;i<names.length;i++){
				 if(value==names[i]){
					 rs = '<font color="'+ colors[i] +'">'+ value +'</font>';
				 } 
		    }
		}
		return rs;
	},
	/**
	 * echarts tooltip position
	 * 调整此处的tooltip的位置，使得tooltip从div的左侧飘过来
	 * @param id
	 * @param p [x, y]
	 * @returns {Array}
	 */
	echartsTooltipPosition: function(id, p) {
		if (!Util.undfd(id) && !Util.nvl(id)
				&& !Util.undfd(p) && !Util.nvl(p) && p.length == 2) {
			var box = Util.id(id);
			if (!Util.undfd(box) && !Util.nvl(box)) {
				var tip = $(box).find('div .echarts-tooltip');
				if (!Util.undfd(tip) && !Util.nvl(tip)) {
					if ($(box).width() - p[0] - tip.width() - 20 < 0) {
		                p[0] = p[0] - tip.width() - 40;
		            }
				}
			}
			if(p[0] < 0){
				p[0] = Math.abs(p[0]);
			}
            return [p[0], p[1]];
		}
	},
	/**
	 * 监听对象属性(包括dom对象、js普通对象等一切Object,只适用脚本赋值[即等号赋值],不适用鼠标/键盘操作赋值[可使用onpropertychange/oninput等事件])
	 * @param obj
	 * @param prop
	 * @param handler
	 */
	watch:function(obj,prop,handler)
	{	
        var oldval = obj[prop], newval = oldval,
        getter = function ()
        {
            return newval;
        },
        setter = function (val) 
        {        	
            oldval = newval;            
            newval=val;              
            handler(oldval, newval);
        };
        if (Object.defineProperty)
        {           
             Object.defineProperty(obj, prop, {get: getter,set: setter});
        }
        else if (obj.__defineGetter__ && obj.__defineSetter__) 
        {
        	obj.__defineGetter__(prop, getter);
        	obj.__defineSetter__(prop, setter);
        }	
	},
	/**
	 * 获取时间轴data
	 */
	getTimeLineData: function(y){
		var y = (!Util.isUndefined(y) && !Util.nvl(y)) ? y : (new Date()).getFullYear();
		return [y +'-01-01', y +'-02-01', y +'-03-01', y +'-04-01', y +'-05-01', y +'-06-01'
		        , y +'-07-01', y +'-08-01', y +'-09-01', y +'-10-01', y +'-11-01', y +'-12-01'];
	},
	/**
	 * 截取容器id内容为图片，弹出框(图片另存为)
	 * 使用html2canvas.js
	 * @param id 容器id
	 */
	saveAsImg: function(id) {
		if(id && $('#'+ id)) {
			var winId = 'saveAsImg_win';
			var imgId = 'saveAsImg_img';
			if(!($('#'+ winId)[0])){
				// 保存图片弹出win
				var w = '<div class="easyui-dialog" id="'+ winId +'" data-options="modal: true,closed: true,title: \'保存图片\'">'
							+'<img id="'+ imgId +'" title="右键->图片另存为" alt="">'
						+'</div>';
				$('body').append(w);
				$.parser.parse('#'+ winId);
			}
			html2canvas($('#'+ id), {
	            allowTaint: true,
	            taintTest: false,
	            onrendered: function(canvas) {
	            	var canvasId = 'mycanvas';
	                canvas.id = canvasId;
	                // 生成base64图片数据
					var dataUrl = canvas.toDataURL();
					var img = $('#'+ imgId);
					if (!Util.undfd(img) && !Util.nvl(img)) {
						var imgw = $('#'+ id).width();// 图片宽
						var imgh = $('#'+ id).height();// 图片高
						img.css('width', imgw);
						img.css('height', imgh);
						img.attr('src', dataUrl);
						$('#'+ winId).dialog({
							height: imgh+ 60,
							width: imgw + 20
						}).dialog('open').dialog('center');
					}
	            }
			});
		}
	},
	/**
	 * echarts图形另存为图片（弹出新窗口）【IE不支持】
	 * @param chart
	 */
	chartSaveAsImg: function(chart) {
		if (chart && chart.getDataURL()) {
			window.open(chart.getDataURL('png'), '右键->图片另存为');
		}
	},
	/**
	 * 计算各个模块滑块区间
	 * @param module 模块
	 * @param thrshd 阀值数组
	 */
	calcSliderInterval: function(module, thrshd) {
		var min = 0, max = 1;
		for(var i = 0; i < thrshd.length; i++){
			if (!Util.nvl(thrshd[i].MIN_THRSHD)
					&& !Util.undfd(thrshd[i].MIN_THRSHD)
					&& parseFloat(thrshd[i].MIN_THRSHD) < min) {
				min = parseFloat(thrshd[i].MIN_THRSHD);
			}
			if (!Util.nvl(thrshd[i].MAX_THRSHD)
					&& !Util.undfd(thrshd[i].MAX_THRSHD)
					&& parseFloat(thrshd[i].MAX_THRSHD) > max) {
				max = parseFloat(thrshd[i].MAX_THRSHD);
			}
		}
		return [min, max];
	},
	/**
	 * 秒-->d天h时m分
	 * @param val 秒
	 */
	secondToDHM: function(val){
		if(Util.isUndefined(val) || Util.nvl(val)){
			return '';
		}
		var s = Math.abs(val);// 使用绝对值计算,负数在结果前加-
		// d 86400
		var d = parseInt(s / 86400);
		// h  3600
		var h = parseInt(s % 86400 / 3600);
		// m 60
		var m = (s % 3600 / 60).toFixed(0);
		// 分钟小时是否有进位的情况
		if(m == 60){
			// 分钟进位
			h += 1;
			m = 0;
		}
		if(h == 24){
			// 小时进位
			d += 1;
			h = 0;
		}
		var dhm = '';
		if(d != 0){
			dhm += d +'天';
		}
		if(h != 0){
			dhm += h +'小时';
		}
		if(m != 0){
			dhm += m +'分';
		}else{
			if(dhm.length == 0){
				dhm += m +'分';
			}
		}
		if(val < 0){
			dhm = '-'+ dhm;
		}
		return dhm;
	},
	/**
	 * 秒转为带小数点的天
	 * @param {} val
	 * @return {String}
	 */
	secondToDays: function(val){
		if(Util.undfd(val) || Util.nvlExc(val)){
			return '';
		}
		var s = Math.abs(val);// 使用绝对值计算,负数在结果前加-
		// d 86400
		var d = (s / 86400).toFixed(2);
		
		if(val < 0){
			d = '-'+ d;
		}
		return d;
	},
	/**
	 * 添加数据位空的省份
	 * @param ds [{name: 'province name',value: numer},...]
	 */
	addEmptyDataProvince: function(ds) {
		if (ds) {
			var ns = '';
			for (var i = 0; i < ds.length; i++) {
				ns += ds[i]['name'] +',';
			}
			// {'province name': {name: 'province name',value: -1},,,}
			var eds = Global.emptyDataProvinceDs();
			for (var name in eds) {
				// 此省份在ds里不存在（无数据）
				if (ns.indexOf(name +',') == -1) {
					ds.push(eds[name]);
				}
			}
		}
		return ds;
	},
	/**
	 * 格式化标签
	 * @param txt 内容
	 * @param unitLen 单位长度
	 * @param split 分隔符
	 */
	formatLabel: function(txt, unitLen, split) {
		var rs = '';
		if (txt) {
			unitLen = Util.nvl(unitLen) ? 4 : unitLen;
			if (txt.length > unitLen) {
				split = split ? split : '\n';// 默认换行符
				var splits = Math.ceil(txt.length / unitLen);// 需要分割成的段数
				for (var i = 0; i < splits; i++) {
                    var temp = '';// 每次截取的字符串  
                    var start = i * unitLen;// 开始截取的位置  
                    var end = start + unitLen;// 结束截取的位置  
                    temp = txt.substring(start, end);
                    // 未到最后一段，末尾加分隔符
                    if (i < (splits - 1)) {
                    	temp += split;
                    }
                    rs += temp;
                }
			} else {
				rs = txt;
			}
		}
		return rs;
	},
	/**
	 * 对象数组排序
	 * @param key 字段key
	 * @param sortOrder 排序顺序: asc-升序 desc-降序
	 */
	objArrSort: function(key, sortOrder) {
		sortOrder = sortOrder ? sortOrder.toLowerCase() : 'asc';
		return function (objN, objM) {
			var valN = objN[key];
			var valM = objM[key];
			if (sortOrder == 'desc') {// 降序
				if (valN < valM) {
					return 1;
				} else if (valN > valM) {
					return -1;
				} else {
					return 0;
				}
			} else {
				if (valN > valM) {
					return 1;
				} else if (valN < valM) {
					return -1;
				} else {
					return 0;
				}
			}
		}
	}
};
